iT邦幫忙

2026 iThome 鐵人賽

0
AI Engineering

Java × AI:30天打造智慧健康助理系列 第 9 篇

讓 Spring Boot 接收 JSON

  • 分享至 

  • xImage
  •  

Day 9|讓 Spring Boot 接收 JSON

昨天的 Day 8,我們成功讓 BMI API 從原本回傳一段文字,升級成回傳 JSON 格式。

例如:

{
  "height": 162,
  "weight": 50,
  "bmi": 19.05
}

這樣不只讓資料更有結構,也方便未來前端網頁或其他程式讀取。

不過目前還有一個問題:

我們一直都是透過網址傳送資料,如果之後要輸入更多健康資訊,難道全部都要寫在網址裡面嗎?

例如:

/bmi?height=162&weight=50

只有兩個參數還算簡單。

但如果未來還想加入睡眠時間、飲水量、運動時間等資料,網址就會變得越來越長。

所以今天決定學習另一種傳送資料的方式:

使用 HTTP POST 搭配 @RequestBody,讓 Spring Boot 直接接收 JSON 格式的資料!


一、先認識 HTTP Method

前幾天建立 API 時,我們一直使用:

@GetMapping

例如:

@GetMapping("/bmi")

這代表 API 會處理 HTTP GET Request。

不過 HTTP 其實不只有 GET,還有其他常見的 Method。

Method 常見用途
GET 取得資料
POST 提交資料或建立資源
PUT 更新或取代資源
PATCH 部分更新資料
DELETE 刪除資料

例如未來智慧健康助理可能會有:

GET /health-records

取得健康紀錄。

POST /health-records

新增健康紀錄。

DELETE /health-records/1

刪除編號為 1 的健康紀錄。

當然,這些目前都還只是規劃中的功能。

今天先從 POST 開始!


二、GET 和 POST 有什麼不同?

之前使用 GET 時,會把資料放在網址的 Query Parameters 裡。

例如:

http://localhost:8080/bmi?height=162&weight=50

Spring Boot 透過:

@RequestParam

取得資料。

但是 POST 可以把資料放在 HTTP Request Body 裡面。

例如:

{
  "height": 162,
  "weight": 50
}

這樣就不需要把每個欄位都放在網址中。

簡單比較:

比較項目 GET POST
常見用途 讀取資料 提交資料
資料傳遞 常使用網址參數 常使用 Request Body
Spring Boot @GetMapping @PostMapping
接收資料 @RequestParam @RequestBody
瀏覽器直接測試 較方便 通常需要 API 測試工具

不過要注意,POST 並不代表資料會自動加密。

如果涉及個人健康資訊,仍然需要 HTTPS、身分驗證及適當的資料保護措施。


三、@RequestBody 是什麼?

今天最重要的新東西就是:

@RequestBody

它可以讓 Spring Boot 讀取 HTTP Request Body,並將其中的 JSON 資料轉換成 Java 可以使用的物件。

例如使用者傳送:

{
  "height": 162,
  "weight": 50
}

Spring Boot 就可以將這些資料轉換成 Java 物件,再交給程式進行處理。

整個流程大概是:

使用者
   ↓
發送 POST Request
   ↓
Request Body(JSON)
   ↓
Spring Boot
   ↓
@RequestBody
   ↓
Java 物件
   ↓
進行資料處理
   ↓
回傳結果

這就是今天要完成的功能。


四、建立 HealthRequest 類別

前幾天都是直接在 Controller 裡面使用:

@RequestParam double height

但是今天要接收 JSON,因此可以先建立一個 Java Class,用來表示使用者傳入的資料。

建立:

HealthRequest.java

程式如下:

public class HealthRequest {

    private double height;
    private double weight;

    public HealthRequest() {
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
}

這裡使用了 Java 的封裝概念。

我們先將:

private double height;
private double weight;

設定為 private。

再透過 Getter 和 Setter 讀取或修改資料。

例如:

request.getHeight()

就可以取得身高。

而:

request.getWeight()

就可以取得體重。

Spring Boot 在常見的 Jackson JSON 設定下,可以利用這個類別的無參數建構子及 Setter,將 JSON 資料轉換成 HealthRequest 物件。


五、建立第一個 POST API

接下來建立:

HealthController.java

今天先做一個簡單的 API,讓使用者傳入身高與體重,然後回傳 BMI。

完整程式:

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class HealthController {

    @PostMapping("/health/bmi")
    public Map<String, Object> calculateBMI(
            @RequestBody HealthRequest request) {

        Map<String, Object> result = new HashMap<>();

        double height = request.getHeight();
        double weight = request.getWeight();

        if (!Double.isFinite(height) ||
            !Double.isFinite(weight) ||
            height <= 0 || weight <= 0) {

            result.put("error",
                    "Height and weight must be positive numbers.");

            return result;
        }

        double heightInMeters = height / 100;

        double bmi = weight / (heightInMeters * heightInMeters);

        if (!Double.isFinite(bmi)) {
            result.put("error", "Unable to calculate BMI.");
            return result;
        }

        double roundedBmi = Math.round(bmi * 100.0) / 100.0;

        result.put("height", height);
        result.put("weight", weight);
        result.put("bmi", roundedBmi);

        return result;
    }
}

這次使用的路徑是:

POST /health/bmi

因此不會和昨天的:

GET /bmi

產生衝突。


六、認識 @PostMapping

今天第一個新 Annotation:

@PostMapping("/health/bmi")

它代表當 Spring Boot 收到:

POST /health/bmi

就會執行對應的 Method。

這和之前的:

@GetMapping("/bmi")

概念很接近。

只是兩者處理的 HTTP Method 不同。

目前可以先記成:

@GetMapping → 處理 GET

@PostMapping → 處理 POST

七、認識 @RequestBody

接下來是今天最重要的地方:

@RequestBody HealthRequest request

它代表 Spring Boot 會將 Request Body 中的 JSON 資料,轉換成 HealthRequest 物件。

例如傳入:

{
  "height": 162,
  "weight": 50
}

程式就可以透過:

double height = request.getHeight();
double weight = request.getWeight();

取得資料。

這樣就不需要像之前一樣,在網址中寫:

?height=162&weight=50

而是可以直接傳送 JSON。


八、要怎麼測試 POST API?

前幾天都是直接在瀏覽器網址列輸入網址。

但今天使用 POST,因此不能只靠在網址列輸入路徑來測試。

我們可以使用 Postman 等 API 測試工具。

Step 1:選擇 POST

將 HTTP Method 設定成:

POST

Step 2:輸入網址

http://localhost:8080/health/bmi

Step 3:設定 Body

選擇:

Body → raw → JSON

輸入:

{
  "height": 162,
  "weight": 50
}

並確認 Request Header 包含:

Content-Type: application/json

Step 4:送出 Request

按下 Send。

如果程式正常執行,預期會收到:

{
  "height": 162.0,
  "weight": 50.0,
  "bmi": 19.05
}

這樣就代表 Spring Boot 成功接收 JSON,並完成 BMI 計算!


九、GET 和 POST 的程式比較

回顧昨天的寫法:

@GetMapping("/bmi")
public Map<String, Object> calculateBMI(
        @RequestParam double height,
        @RequestParam double weight) {
    // BMI 計算
}

今天改成:

@PostMapping("/health/bmi")
public Map<String, Object> calculateBMI(
        @RequestBody HealthRequest request) {
    // BMI 計算
}

最大的差別就是資料的接收方式。

Day 8

GET /bmi?height=162&weight=50
        ↓
@RequestParam
        ↓
取得 height、weight

Day 9

POST /health/bmi
        ↓
Request Body
        ↓
JSON
        ↓
@RequestBody
        ↓
HealthRequest 物件

雖然最後都是計算 BMI,但今天的方式更適合接收包含多個欄位的資料。


十、如果未來要加入更多健康資料呢?

現在 HealthRequest 只有:

private double height;
private double weight;

但之後可以慢慢擴充。

例如:

private double sleepHours;
private int waterIntake;
private int exerciseMinutes;

未來就可以接收:

{
  "height": 162,
  "weight": 50,
  "sleepHours": 7,
  "waterIntake": 1500,
  "exerciseMinutes": 30
}

這樣使用者就可以一次提交多種健康資料。

不過目前我們還沒有建立資料庫,所以這些資料只會在這次 Request 中被處理,並不會自動儲存下來。

等之後學到資料庫,再慢慢加入健康紀錄的儲存功能。


十一、今天遇到錯誤怎麼辦?

第一次使用 POST 時,可能會遇到一些問題。

1. 404 Not Found

可能原因:

  • API 路徑輸入錯誤
  • Controller 沒有被 Spring Boot 掃描到
  • 專案沒有正確啟動

2. 405 Method Not Allowed

可能是使用 GET 去呼叫只支援 POST 的 API。

例如直接在瀏覽器輸入:

http://localhost:8080/health/bmi

瀏覽器通常會發送 GET Request,但我們設定的是:

@PostMapping

所以就可能出現 405。

3. 400 Bad Request

可能原因:

  • JSON 格式錯誤
  • 傳入的資料型別不正確
  • Request Body 無法成功轉換成 Java 物件

4. 415 Unsupported Media Type

可能是沒有正確設定:

Content-Type: application/json

因此 Spring Boot 無法依照預期的格式處理資料。

遇到這些問題時,可以先檢查 HTTP Method、URL、Header 和 Body。


十二、今天的智慧健康助理進步了什麼?

Day 7:

接收網址參數
    ↓
計算 BMI
    ↓
回傳文字

Day 8:

接收網址參數
    ↓
計算 BMI
    ↓
回傳 JSON

Day 9:

接收 POST Request
    ↓
讀取 JSON
    ↓
轉換成 Java 物件
    ↓
計算 BMI
    ↓
回傳 JSON

今天最大的進步,就是系統已經可以同時處理 JSON 輸入與 JSON 輸出。

這也讓我們離未來的 AI API 串接又更近了一步!


Day 9 小結

今天第一次使用:

@PostMapping

以及:

@RequestBody

讓 Spring Boot 不只能透過網址參數取得資料,也能直接接收 JSON。

今天學到的重點包括:

  1. HTTP GET 與 POST 的差別
  2. @PostMapping 的用途
  3. @RequestBody 如何接收 JSON
  4. 建立 HealthRequest Java 類別
  5. 使用 Postman 測試 POST API
  6. 了解常見的 HTTP 錯誤

現在我們的智慧健康助理已經可以:

接收 JSON → 轉換成 Java 物件 → 處理健康資料 → 回傳 JSON。

雖然目前還是在做 BMI,但今天學到的資料傳遞方式,未來也能應用在健康紀錄與 AI 功能中。


明日預告

Day 10|讓程式更有條理!認識 Controller 與 Service 分層

目前我們把接收 Request 和 BMI 計算邏輯都寫在 Controller 裡面。

雖然程式可以正常運作,但如果未來要加入睡眠、飲水、運動等功能,Controller 可能會越來越長。

所以下一篇準備認識:

  • Controller 負責什麼?
  • Service 負責什麼?
  • 為什麼要將程式邏輯分開?
  • 如何把 BMI 計算移到 Service?

讓智慧健康助理不只是功能越來越多,程式結構也能越來越清楚!


上一篇
讓 Spring Boot 回傳 JSON
下一篇
認識 Controller 與 Service 分層
系列文
Java × AI:30天打造智慧健康助理 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言